#ifndef __OPSIMPLS__
#define __OPSIMPLS__

#include "matvec.h"

/* OpenPFEM */
void MatrixCreate_OpenPFEM(MATRIX *matrix);
void MatrixDestroy_OpenPFEM(MATRIX *matrix);
void MatrixSturctureCompare_OpenPFEM(MATRIX *A, MATRIX *B, NONZERO_STRUCT *nonzero_struct);
void MatrixScale_OpenPFEM(DOUBLE alpha, MATRIX *A);
void MatrixAxpby_OpenPFEM(DOUBLE alpha, MATRIX *A,  DOUBLE beta, MATRIX *B, NONZERO_STRUCT nonzero_struct);

void VectorCreateByMatrix_OpenPFEM(VECTOR **vector, MATRIX *matrix);
void VectorCreateByMatrixT_OpenPFEM(VECTOR **vector, MATRIX *matrix);
void MatrixVectorMult_OpenPFEM(MATRIX *A, VECTOR *x, VECTOR *y);
void MatrixTransposeVectorMult_OpenPFEM(MATRIX *A, VECTOR *x, VECTOR *y);
void MatrixVectorMultAdd_OpenPFEM(MATRIX *A, VECTOR *x, VECTOR *y);
void MatrixVectorMultSub_OpenPFEM(MATRIX *A, VECTOR *x, VECTOR *y);

void VectorsCreateByMatrix_OpenPFEM(VECTORS **vectors, MATRIX *matrix, INT num);
void VectorsCreateByMatrixT_OpenPFEM(VECTORS **vectors, MATRIX *matrix, INT num);
void MatrixVectorsMult_OpenPFEM(MATRIX *A, VECTORS *x, VECTORS *y);
void MatrixTransposeVectorsMult_OpenPFEM(MATRIX *A, VECTORS *x, VECTORS *y);

void VectorCreate_OpenPFEM(VECTOR *vector);
void VectorDestroy_OpenPFEM(VECTOR *vector);
void VectorGetArray_OpenPFEM(VECTOR *vector, DOUBLE **data);
void VectorScale_OpenPFEM(DOUBLE alpha, VECTOR *x);
void VectorAxpby_OpenPFEM(DOUBLE alpha, VECTOR *x, DOUBLE beta, VECTOR *y);
void VectorNorm_OpenPFEM(VECTOR *vector, DOUBLE *alpha);

void VectorsCreate_OpenPFEM(VECTORS *vectors);
void VectorsDestroy_OpenPFEM(VECTORS *vectors);
void VectorsGetArray_OpenPFEM(VECTORS *vectors, DOUBLE **data);
void VectorsRestoreArray_OpenPFEM(VECTORS *vectors, DOUBLE **data);

#if defined(PETSC_USE)
void MatrixCreate_PETSc(MATRIX *matrix);
void MatrixDestroy_PETSc(MATRIX *matrix);
void MatrixSturctureCompare_PETSc(MATRIX *A, MATRIX *B, NONZERO_STRUCT *nonzero_struct);
void MatrixScale_PETSc(DOUBLE alpha, MATRIX *A);
void MatrixAxpby_PETSc(DOUBLE alpha, MATRIX *A,  DOUBLE beta, MATRIX *B, NONZERO_STRUCT nonzero_struct);

void VectorCreateByMatrix_PETSc(VECTOR **vector, MATRIX *matrix);
void VectorCreateByMatrixT_PETSc(VECTOR **vector, MATRIX *matrix);
void MatrixVectorMult_PETSc(MATRIX *A, VECTOR *x, VECTOR *y);
void MatrixTransposeVectorMult_PETSc(MATRIX *A, VECTOR *x, VECTOR *y);
void MatrixVectorMultAdd_PETSc(MATRIX *A, VECTOR *x, VECTOR *y);
void MatrixVectorMultSub_PETSc(MATRIX *A, VECTOR *x, VECTOR *y);

void VectorCreate_PETSc(VECTOR *vector);
void VectorDestroy_PETSc(VECTOR *vector);
void VectorGetArray_PETSc(VECTOR *vector, DOUBLE **data);
void VectorScale_PETSc(DOUBLE alpha, VECTOR *x);
void VectorAxpby_PETSc(DOUBLE alpha, VECTOR *x, DOUBLE beta, VECTOR *y);
void VectorNorm_PETSc(VECTOR *vector, DOUBLE *alpha);
#endif

#if defined(SLEPC_USE)
void VectorsCreateByMatrix_SLEPc(VECTORS **vectors, MATRIX *matrix, INT num);
void VectorsCreateByMatrixT_SLEPc(VECTORS **vectors, MATRIX *matrix, INT num);
void MatrixVectorsMult_SLEPc(MATRIX *A, VECTORS *x, VECTORS *y);
void MatrixTransposeVectorsMult_SLEPc(MATRIX *A, VECTORS *x, VECTORS *y);

void VectorsCreate_SLEPc(VECTORS *vectors);
void VectorsDestroy_SLEPc(VECTORS *vectors);
void VectorsGetArray_SLEPc(VECTORS *vectors, DOUBLE **data);
void VectorsRestoreArray_SLEPc(VECTORS *vectors, DOUBLE **data);
#endif

#endif